// This MFC Samples source code demonstrates using MFC Microsoft Office Fluent User Interface 
// (the "Fluent UI") and is provided only as referential material to supplement the 
// Microsoft Foundation Classes Reference and related electronic documentation 
// included with the MFC C++ library software.  
// License terms to copy, use or distribute the Fluent UI are available separately.  
// To learn more about our Fluent UI licensing program, please visit 
// http://msdn.microsoft.com/officeui.
//
// Copyright (C) Microsoft Corporation
// All rights reserved.

// SketchView.cpp : implementation of the CSketchView class
//

#include "stdafx.h"
#include "Sketch.h"

#include "SketchDoc.h"
#include "SketchView.h"
#include "TxnMgr.h"
#include "Geom/Geometry2D.h"
#include <cmath>


// CSketchView

IMPLEMENT_DYNCREATE(CSketchView, CView)

BEGIN_MESSAGE_MAP(CSketchView, CView)
	// Standard printing commands
	ON_COMMAND(ID_FILE_PRINT, &CView::OnFilePrint)
	ON_COMMAND(ID_CANCEL_EDIT_SRVR, &CSketchView::OnCancelEditSrvr)
	ON_COMMAND(ID_FILE_PRINT_DIRECT, &CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CSketchView::OnFilePrintPreview)
	ON_WM_MOUSEMOVE()
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONUP()
	ON_COMMAND(ID_EDIT_REDO, &CSketchView::OnEditRedo)
	ON_UPDATE_COMMAND_UI(ID_EDIT_REDO, &CSketchView::OnUpdateEditRedo)
	ON_COMMAND(ID_EDIT_UNDO, &CSketchView::OnEditUndo)
	ON_UPDATE_COMMAND_UI(ID_EDIT_UNDO, &CSketchView::OnUpdateEditUndo)

	ON_COMMAND(ID_SKETCH_LINE, &CSketchView::OnSketchLine)
	ON_UPDATE_COMMAND_UI(ID_SKETCH_LINE, &CSketchView::OnUpdateSketchLine)

	ON_COMMAND(ID_SKETCH_CIRCLE, &CSketchView::OnSketchCircle)
	ON_UPDATE_COMMAND_UI(ID_SKETCH_CIRCLE, &CSketchView::OnUpdateSketchCircle)

	ON_COMMAND(ID_VIEW_SHOWMEMORY, &CSketchView::OnShowMemory)


END_MESSAGE_MAP()

// CSketchView construction/destruction

CSketchView::CSketchView()
{
	// TODO: add construction code here
	m_bPreview = false;
	m_eCurType = kNone;

}

CSketchView::~CSketchView()
{
}

BOOL CSketchView::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: Modify the Window class or styles here by modifying
	//  the CREATESTRUCT cs

	return CView::PreCreateWindow(cs);
}

// CSketchView drawing

void CSketchView::OnDraw(CDC* pDC)
{
	CSketchDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	const TxnVector& allGeometries = pDoc->GetAllGeometries();
	for (TxnVector::const_iterator it = allGeometries.begin(); it != allGeometries.end(); it++)
	{
		//if((*it))
			(*it)->Render(pDC);
	}

	if(m_bPreview) 
	{
		if(m_eCurType == kLine )m_curLine.Render(pDC);
		else if(m_eCurType == kCircle) m_curCircle.Render(pDC);
	}
}


// CSketchView printing


void CSketchView::OnFilePrintPreview()
{
	AFXPrintPreview(this);
}

BOOL CSketchView::OnPreparePrinting(CPrintInfo* pInfo)
{
	// default preparation
	return DoPreparePrinting(pInfo);
}

void CSketchView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: add extra initialization before printing
}

void CSketchView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: add cleanup after printing
}

void CSketchView::OnRButtonUp(UINT nFlags, CPoint point)
{
	ClientToScreen(&point);
	OnContextMenu(this, point);
}

void CSketchView::OnContextMenu(CWnd* pWnd, CPoint point)
{
	theApp.GetContextMenuManager()->ShowPopupMenu(IDR_POPUP_EDIT, point.x, point.y, this, TRUE);
}

// OLE Server support

// The following command handler provides the standard keyboard
//  user interface to cancel an in-place editing session.  Here,
//  the server (not the container) causes the deactivation
void CSketchView::OnCancelEditSrvr()
{
	GetDocument()->OnDeactivateUI(FALSE);
}


// CSketchView diagnostics

#ifdef _DEBUG
void CSketchView::AssertValid() const
{
	CView::AssertValid();
}

void CSketchView::Dump(CDumpContext& dc) const
{
	CView::Dump(dc);
}

CSketchDoc* CSketchView::GetDocument() const // non-debug version is inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CSketchDoc)));
	return (CSketchDoc*)m_pDocument;
}
#endif //_DEBUG

// CSketchView message handlers

void CSketchView::OnMouseMove(UINT nFlags, CPoint point)
{
	if(m_eCurType != kNone) 
	{
		if(m_eCurType == kLine)
		{
			m_curLine.ptEnd.x = point.x;
			m_curLine.ptEnd.y = point.y;
		}
		else if(m_eCurType == kCircle)
		{
			m_curCircle.nRadius = sqrt(double((point.x - m_curCircle.ptCenter.x) * (point.x - m_curCircle.ptCenter.x) + (point.y - m_curCircle.ptCenter.y) * (point.y - m_curCircle.ptCenter.y)));
		}

		this->Invalidate(TRUE);
	}

	CView::OnMouseMove(nFlags, point);
}

void CSketchView::OnLButtonDown(UINT nFlags, CPoint point)
{
	if(m_eCurType != kNone) 
	{
		m_bPreview = true;

		if(m_eCurType == kLine)
		{
			m_curLine.ptStart.x = point.x;
			m_curLine.ptStart.y = point.y;
		}
		else if(m_eCurType == kCircle)
		{
			m_curCircle.ptCenter.x = point.x;
			m_curCircle.ptCenter.y = point.y;
		}
	}

	CView::OnLButtonDown(nFlags, point);
}

void CSketchView::OnLButtonUp(UINT nFlags, CPoint point)
{
	if (m_eCurType != kNone)
	{
		// TODO: Add your message handler code here and/or call default
		CSketchDoc* pDoc = GetDocument();

		pDoc->GetTxnMgr()->StartTxn();

		Geometry2D* pGeom = NULL;
		if (m_eCurType == kLine)
		{
			pGeom = new Line(m_curLine);
		}
		else if(m_eCurType == kCircle)
		{
			pGeom = new Circle(m_curCircle);
		}
		pDoc->AddGeometry(pGeom);

		pDoc->GetTxnMgr()->EndTxn();

		m_bPreview = false;
		m_eCurType = kNone;

	}


	CView::OnLButtonUp(nFlags, point);

	

}

void CSketchView::OnEditRedo()
{
	CSketchDoc* pDoc = GetDocument();

	pDoc->GetTxnMgr()->RedoTxn();
	this->Invalidate(TRUE);
	// TODO: Add your command handler code here
}

void CSketchView::OnUpdateEditRedo(CCmdUI *pCmdUI)
{
	CSketchDoc* pDoc = GetDocument();

	// TODO: Add your command update UI handler code here
	pCmdUI->Enable(pDoc->GetTxnMgr()->Redoable());

}

void CSketchView::OnEditUndo()
{
	CSketchDoc* pDoc = GetDocument();

	// TODO: Add your command handler code here
	pDoc->GetTxnMgr()->UndoTxn();
	this->Invalidate(TRUE);
}

void CSketchView::OnUpdateEditUndo(CCmdUI *pCmdUI)
{
	// TODO: Add your command update UI handler code here
	CSketchDoc* pDoc = GetDocument();

	pCmdUI->Enable(pDoc->GetTxnMgr()->Undoable());
}

void CSketchView::OnSketchLine()
{
	m_eCurType = kLine;
}

void CSketchView::OnUpdateSketchLine(CCmdUI *pCmdUI)
{
	if(m_eCurType == kLine) pCmdUI->SetCheck(true);
	else pCmdUI->SetCheck(false);
}

void CSketchView::OnSketchCircle()
{
	m_eCurType = kCircle;
}

void CSketchView::OnUpdateSketchCircle(CCmdUI *pCmdUI)
{
	if(m_eCurType == kCircle) pCmdUI->SetCheck(true);
	else pCmdUI->SetCheck(false);
}

void CSketchView::OnShowMemory()
{
	HeapMgr::Get()->Dump();
}